package ph.com.gs3.formalistics.utilities;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import ph.com.gs3.formalistics.model.valueobjects.application.FormField;
import android.content.Context;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;

public class FieldBuilder {

	public static final String TAG = FieldBuilder.class.getSimpleName();

	private Context context;

	private LayoutParams lpFillWidth;

	public static enum EditTextType {
		MULTILINE, NORMAL
	}

	public FieldBuilder(Context context) {
		this.context = context;

		lpFillWidth = new LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
		        LinearLayout.LayoutParams.WRAP_CONTENT);
	}

	public View createField(FormField formField) {

		switch (formField.getType()) {
			case TEXT_FIELD:
				return createEditText(formField, EditTextType.NORMAL);
			case TEXT_AREA:
				return createEditText(formField, EditTextType.MULTILINE);
			case CHECK_BOX_GROUP:
				return createCheckBoxGroup(formField);
			case RADIO_BUTTON_GROUP:
				return createRadioButtonGroup(formField);
			default:
				return null;
		}

	}

	// =============================================================================
	// Field Builders

	public View createEditText(FormField formField, EditTextType type) {

		LinearLayout container = createLabeledDefaultContainer(formField.getLabel(),
		        formField.getId() + "_container");

		EditText etField = new EditText(context);
		etField.setLayoutParams(lpFillWidth);
		etField.setTag(formField.getId());

		if (type == EditTextType.MULTILINE) {
			etField.setSingleLine(false);
			etField.setImeOptions(EditorInfo.IME_FLAG_NO_ENTER_ACTION);
		}

		if (formField.getPlaceHolder() != null) {
			etField.setHint(formField.getPlaceHolder());
		}

		if (formField.getValue() != null) {
			etField.setText(formField.getValue());
		}

		container.addView(etField);

		return container;

	}

	public View createCheckBoxGroup(FormField formField) {

		validateFieldsWithOptions(formField);

		LinearLayout container = createLabeledDefaultContainer(formField.getLabel(),
		        formField.getId() + "_container");

		// initialize checkbox data
		List<String> options = formField.getOptions();
		List<String> selectedOptions = new ArrayList<String>();

		if (formField.getValue() != null) {
			String[] selectedOptionsRaw = formField.getValue().split(",");
			selectedOptions = new ArrayList<String>(Arrays.asList(selectedOptionsRaw));
		} else {
			selectedOptions = new ArrayList<String>();
		}

		// initialize checkbox view
		LinearLayout checkBoxContainer = new LinearLayout(context);

		checkBoxContainer.setOrientation(LinearLayout.VERTICAL);
		checkBoxContainer.setTag(formField.getId());

		for (int i = 0; i < options.size(); i++) {

			String optionString = options.get(i);

			CheckBox cbField = new CheckBox(context);
			cbField.setTag(formField.getId() + "_" + i);

			// check if the option is a value label pair, if it is, set the label as the
			// text,
			if (optionString.contains("|")) {
				cbField.setText(optionString.split("\\|")[1]);
			} else {
				cbField.setText(optionString);
			}

			// check each option that is selected
			if (selectedOptions != null) {
				for (String selectedOption : selectedOptions) {

					if (optionString.contains("|")) {
						String optionValue = optionString.split("\\|")[0];
						if (optionValue.equals(selectedOption.trim())) {
							cbField.setChecked(true);
						}
					} else {
						if (optionString.equals(selectedOption.trim())) {
							cbField.setChecked(true);
						}
					}

				}
			}

			checkBoxContainer.addView(cbField);

		}

		container.addView(checkBoxContainer);

		return container;

	}

	public View createRadioButtonGroup(FormField formField) {

		validateFieldsWithOptions(formField);

		LinearLayout container = createLabeledDefaultContainer(formField.getLabel(),
		        formField.getId() + "_container");

		// initialize data
		List<String> options = formField.getOptions();
		String selectedValue = null;
		String selectedValueRaw = formField.getValue();

		if (selectedValueRaw != null) {
			if (selectedValueRaw.contains("|")) {
				selectedValue = selectedValueRaw.split("\\|")[0];
			} else {
				selectedValue = selectedValueRaw;
			}
		}

		// initialize the view
		RadioGroup radioGroup = new RadioGroup(context);

		radioGroup.setOrientation(RadioGroup.VERTICAL);
		radioGroup.setTag(formField.getId());

		for (int i = 0; i < options.size(); i++) {

			String optionString = options.get(i).trim();
			String optionLabel = optionString;
			String optionStringValue = optionString;

			boolean checked = false;

			RadioButton radioButton = new RadioButton(context);

			// check if the option is value label pair, if it is, divide the option string
			// with | and assign the label and value properly
			if (optionString.contains("|")) {
				String[] splittedOptionString = optionString.split("\\|");

				optionStringValue = splittedOptionString[0];
				optionLabel = splittedOptionString[1];
			}
			radioButton.setText(optionLabel);

			if (selectedValue != null) {
				if (selectedValue.equals(optionStringValue)) {
					checked = true;
				}
			}

			radioButton.setChecked(checked);
			radioGroup.addView(radioButton);

		}

		container.addView(radioGroup);

		return container;

	}

	// =============================================================================
	// Validators

	private void validateFieldsWithOptions(FormField formField) {

		List<String> options = formField.getOptions();

		if (options == null) {
			throw new IllegalStateException("This field (" + formField.getId()
			        + ") must have an options property. It cannot be null.");
		} else if (options.size() <= 0) {
			throw new IllegalStateException("This field (" + formField.getId()
			        + ") must have a non empty options property.");
		}

	}

	// =============================================================================
	// Container Builders

	private LinearLayout createLabeledDefaultContainer(String label, String tag) {

		LinearLayout container = createDefaultContainer(tag);

		TextView tvLabel = new TextView(context);
		tvLabel.setText(label);
		container.addView(tvLabel);

		return container;

	}

	private LinearLayout createDefaultContainer(String tag) {

		LinearLayout container = new LinearLayout(context);

		container.setTag(tag);
		container.setLayoutParams(lpFillWidth);
		container.setOrientation(LinearLayout.VERTICAL);
		return container;

	}

}
